﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Linq;

using alib.Debugging;
using alib.Enumerable;

namespace agree
{
	///////////////////////////////////////////////////////////////////////
	/// 
	[DebuggerDisplay("{ToString(),nq}")]
	public struct Ix1Path
	{
		public Ix1Path(Tfs atfs, ICollection<int> ic)
			: this()
		{
			this.rg_ix1 = ic as int[] ?? ic.ToArray();
			this.atfs = atfs;
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public readonly Tfs atfs;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public readonly int[] rg_ix1;

		int[] to_rg_fix()
		{
			FeatMgr ftm = atfs.ftm;
			FeatureInfo[] rgfi = ftm.feat_arr;

			int c = rg_ix1.Length;
			if (c == 0)
				return alib.Collections.Collection<int>.None;

			int i, j;
			for (i = c - 1; i >= 0; --i)
				if (rg_ix1[i] == 0)
					c--;
			if (c == 0)
				return alib.Collections.Collection<int>.None;

			int[] arr = new int[c];
			for (i = 0, j = 0; j < c; i++)
			{
				int fix, ix1 = rg_ix1[i];
				if (ix1 != 0)
					arr[j++] = (fix = atfs.entries[ix1 - 1].i_feat) < 0 || fix >= rgfi.Length ? -1 : fix;
			}
			return arr;
		}

		public FsPath FsPath { get { return new FsPath(atfs.im, to_rg_fix()); } }

#if DEBUG
		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		TfsSlotRef[] _dbg
		{
			get
			{
				int c = rg_ix1.Length;
				var arr = new TfsSlotRef[c];
				for (int i = 0; i < c; i++)
					arr[i] = new TfsSlotRef(atfs, rg_ix1[i]);
				return arr;
			}
		}

		// don't cache this: it defeats the purpose of the path being saved as ix1's
		String _render_to_string()
		{
			FeatMgr ftm = atfs.ftm;
			FeatureInfo[] rgfi = ftm.feat_arr;

			var sb = new StringBuilder(80);
			int ix1 = 0;
			for (int i = 0; i < rg_ix1.Length; i++)
			{
				if (sb.Length > 0)
					sb.Append('.');
				if ((ix1 = rg_ix1[i]) == 0)
					sb.Append("[TOPMST]");
				else
				{
					int fix = atfs.entries[ix1 - 1].i_feat;
					if (fix < 0 || fix >= rgfi.Length)
						sb.AppendFormat("[???({0})]", fix.ToString());
					else
						sb.Append(rgfi[fix].FEATURE);
				}
			}
			return sb.ToString();
		}

		public override String ToString()
		{
			String s = "  (" + _render_to_string() + ") ";

			Edge e = atfs.entries.Length == 0 ?
							atfs._top_edge :
							atfs.entries[atfs.entries.Length - 1].e;
			s += e.ToString(atfs.ftm, true);
			return s;
		}
#endif

#if CMP
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public static readonly IComparer<TfsPath> Comparer = new _cmp();

		class _cmp : IComparer<TfsPath>
		{
			public int Compare(TfsPath x, TfsPath y)
			{
				return StringComparer.Ordinal.Compare(x.s, y.s);
			}
		};
#endif
	};
	/// 
	///////////////////////////////////////////////////////////////////////
}